﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace MapViewer
{
    [ToolboxItem(true)]
    public partial class MgPropertyPane : UserControl, IPropertyPane
    {
        private string _countFmt;

        public MgPropertyPane()
        {
            InitializeComponent();
            _countFmt = lblCount.Text;

            cmbLayer.ComboBox.SelectedIndexChanged += new EventHandler(OnSelectionLayerChanged);
        }

        class DictionaryPropertyGridAdapter : ICustomTypeDescriptor
        {
            IDictionary _dictionary;

            public DictionaryPropertyGridAdapter(IDictionary d)
            {
                _dictionary = d;
            }

            public string GetComponentName()
            {
                return TypeDescriptor.GetComponentName(this, true);
            }

            public EventDescriptor GetDefaultEvent()
            {
                return TypeDescriptor.GetDefaultEvent(this, true);
            }

            public string GetClassName()
            {
                return TypeDescriptor.GetClassName(this, true);
            }

            public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
            {
                ArrayList properties = new ArrayList();
                foreach (DictionaryEntry e in _dictionary)
                {
                    properties.Add(new DictionaryPropertyDescriptor(_dictionary, e.Key));
                }

                PropertyDescriptor[] props =
                    (PropertyDescriptor[])properties.ToArray(typeof(PropertyDescriptor));

                return new PropertyDescriptorCollection(props);
            }

            public EventDescriptorCollection GetEvents(Attribute[] attributes)
            {
                return TypeDescriptor.GetEvents(this, attributes, true);
            }

            EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents()
            {
                return TypeDescriptor.GetEvents(this, true);
            }

            public TypeConverter GetConverter()
            {
                return TypeDescriptor.GetConverter(this, true);
            }

            public object GetPropertyOwner(PropertyDescriptor pd)
            {
                return _dictionary;
            }

            public AttributeCollection GetAttributes()
            {
                return TypeDescriptor.GetAttributes(this, true);
            }

            public object GetEditor(Type editorBaseType)
            {
                return TypeDescriptor.GetEditor(this, editorBaseType, true);
            }

            public PropertyDescriptor GetDefaultProperty()
            {
                return null;
            }

            PropertyDescriptorCollection
                System.ComponentModel.ICustomTypeDescriptor.GetProperties()
            {
                return ((ICustomTypeDescriptor)this).GetProperties(new Attribute[0]);
            }
        }

        class DictionaryPropertyDescriptor : PropertyDescriptor
        {
            IDictionary _dictionary;
            object _key;

            internal DictionaryPropertyDescriptor(IDictionary d, object key)
                : base(key.ToString(), null)
            {
                _dictionary = d;
                _key = key;
            }

            public override Type PropertyType
            {
                get
                {
                    if (_dictionary[_key] != null)
                    {
                        return _dictionary[_key].GetType();
                    }
                    else
                    {
                        return typeof(object);
                    }
                }
            }

            public override void SetValue(object component, object value)
            {
                _dictionary[_key] = value;
            }

            public override object GetValue(object component)
            {
                return _dictionary[_key];
            }

            public override bool IsReadOnly
            {
                get { return true; } //Property Pane values are not editable
            }

            public override Type ComponentType
            {
                get { return null; }
            }

            public override bool CanResetValue(object component)
            {
                return false;
            }

            public override void ResetValue(object component)
            {
            }

            public override bool ShouldSerializeValue(object component)
            {
                return false;
            }
        }

        private SelectionSet _sset;

        public void Init(SelectionSet set)
        {
            propGrid.SelectedObject = null;
            featureToolStrip.Visible = false;

            if (_sset != null)
            {
                _sset.Dispose();
                _sset = null;

                cmbLayer.ComboBox.Items.Clear();
                _currentLayerFeatures.Clear();
            }

            _sset = set;

            var layerNames = _sset.LayerNames;
            cmbLayer.ComboBox.Items.AddRange(layerNames);
            if (layerNames.Length > 0)
                cmbLayer.SelectedIndex = 0;

            controlToolStrip.Visible = (layerNames.Length > 0);
        }

        public SelectedFeature CurrentFeature
        {
            get
            {
                var idx = this.CurrentSelectedFeatureIndex;
                if (idx >= 0)
                    return _currentLayerFeatures[idx];

                return null;
            }
        }

        void OnSelectedFeatureChanged()
        {
            var feat = this.CurrentFeature;
            if (feat != null)
            {
                propGrid.SelectedObject = new DictionaryPropertyGridAdapter(feat.Properties);
            }
        }

        private List<SelectedFeature> _currentLayerFeatures = new List<SelectedFeature>();

        void OnSelectionLayerChanged(object sender, EventArgs e)
        {
            if (cmbLayer.SelectedItem != null)
            {
                var layerName = cmbLayer.SelectedItem.ToString();
                _currentLayerFeatures.Clear();

                foreach (var feat in _sset.GetFeaturesForLayer(layerName))
                {
                    _currentLayerFeatures.Add(feat);
                }

                if (_currentLayerFeatures.Count > 0)
                {
                    lblCount.Text = string.Format(_countFmt, _currentLayerFeatures.Count);
                    featureToolStrip.Visible = true;
                    this.CurrentSelectedFeatureIndex = 0;
                }
                else
                {
                    featureToolStrip.Visible = false;
                }
            }
        }

        internal int CurrentSelectedFeatureIndex
        {
            get
            {
                int idx;
                if (int.TryParse(txtPosition.Text, out idx))
                    return idx - 1;

                return 0;
            }
            set
            {
                txtPosition.Text = (value + 1).ToString();
                OnSelectedFeatureChanged();
            }
        }

        public event EventHandler RequestZoomToCurrentFeature;

        private void btnZoomCurrent_Click(object sender, EventArgs e)
        {
            if (this.CurrentFeature != null)
            {
                var handler = this.RequestZoomToCurrentFeature;
                if (handler != null)
                    handler(this, EventArgs.Empty);
            }
        }

        private void btnPrevFeature_Click(object sender, EventArgs e)
        {
            var idx = this.CurrentSelectedFeatureIndex;
            if (idx > 0)
            {
                idx--;
            }
            else
            {
                idx = 0;
            }
            this.CurrentSelectedFeatureIndex = idx;
        }

        private void btnNextFeature_Click(object sender, EventArgs e)
        {
            var idx = this.CurrentSelectedFeatureIndex;
            if (idx < 0)
            {
                idx = 0;
            }
            else
            {
                if (idx < _currentLayerFeatures.Count - 1)
                    idx++;
                else
                    idx = _currentLayerFeatures.Count - 1;
            }
            this.CurrentSelectedFeatureIndex = idx;
        }
    }
}
